/*
    jQuery for scaling
    Copyright (c) 2010 Keiji Hokamura (famteam, Johnnybroccolii)
    This plugin available for use in all personal or commercial projects under both MIT and GPL licenses.
 */

(function($) {
	var methods = {
		exactFit: function (settings, target) {
			return target.data($.scaler.DATA, {}).each(function() {
				var self = $(this);
				var data = self.data($.scaler.DATA);
				
				data.origialSize = {
					width: self.width(),
					height: self.height()
				};
	
				fit();
				$(window).resize(fit);
				data.handler = fit;
				function fit() {
					if (settings.widthFit) {
						var width = $(window).width() - settings.marginWidth;
						if (settings.minimumWidth != null && width < settings.minimumWidth) {
							self.width(settings.minimumWidth);
						}
						else if (settings.maxWidth != null && width > settings.maxWidth) {
							self.width(settings.maxWidth - settings.marginWidth);
						}
						else {
							self.width(width);
						}
						if (settings.follower != null) {
							settings.follower.width(self.width());
						}
					}
					if (settings.heightFit) {
						var height = $(window).height() - settings.marginHeight;
						if (settings.minimumHeight != null && height < settings.minimumHeight) {
							self.height(settings.minimumHeight);
						}
						else if (settings.maxHeight != null && height > settings.maxHeight) {
							self.height(settings.maxHeight - settings.marginHeight);
						}
						else {
							self.height(height);
						}
						if (settings.follower != null) {
							settings.follower.height(self.height());
						}
					}
					if (data.initialized) {
						if (settings.initializeHandler != null) {
							settings.initializeHandler(self);
						}
						data.initialized = true;
					}
				}
			});
		},
		enoughSize: function(settings, target) {
			target.parent().css('display', 'block').css('position', 'absolute');
			return this.data($.scaler.DATA, {
				originalSize: {
					width: this.width(),
					height: this.height()
				}
			}).css('display', 'block').css('position', 'absolute').each(function() {
				var self = $(this);
				var data = self.data($.scaler.DATA);
	
				fit();
				$(window).resize(fit);
				data.handler = fit;
				function fit() {
					var windowWidth = $(window).width();
					var widthRatio = windowWidth / self.width();
					var windowHeight = $(window).height();
					var heightRatio = windowHeight / self.height();
	
					self.parent().width(windowWidth).height(windowHeight).css('overflow', 'hidden');
	
					if (Math.abs(widthRatio) > Math.abs(heightRatio)) {
						var height = self.height() * widthRatio;
						var top;
						switch (settings.horizontalDatum) {
							case $.scaler.CENTER:
								top = (windowHeight - height) / 2;
								break;
							case $.scaler.TOP:
								top = 0;
								break;
							case $.scaler.BOTTOM:
								top = windowHeight - height;
								break;
						}
						self.height(height).width(windowWidth).css('top', top);
					} 
					else {
						var width = self.width() * heightRatio;
						var left;
						switch (settings.verticalDatum) {
							case $.scaler.CENTER:
								left = (windowWidth - width) / 2;
								break;
							case $.scaler.LEFT:
								left = 0;
								break;
							case $.scaler.RIGHT:
								left = windowWidth - width;
								break;
						}
						self.width(self.width() * heightRatio).height(windowHeight).css('left', left);
					}
					if (data.initialized && settings.initializeHandler != null) {
						settings.initializeHandler(self);
						data.initialized = true;
					}
				}
			});
		},
		cancel: function(target) {
			return target.each(function() {
				var data = $(this).data($.scaler.DATA);
				if (data != null && data.handler != null) {
					$(window).unbind('resize', data.handler);
					$(this).data($.scaler.DATA, null);
				}
			});
		},
		adjust: function(target) {
			return target.each(function() {
				var fitHandler = $(this).data($.scaler.DATA).handler;
				if (fitHandler != null) {
					fitHandler();
				}
			});
		},
		ratio: function() {
			var data = this.data($.scaler.DATA);
			if (data != null) {
				return this.width() / data.originalSize.width;
			}
			else {
				return null;
			}
		}
	};
	
	$.fn.scaler = function(settings) {
		settings = $.extend({
			action: $.scaler.EXACT_FIT,
			initializeHandler: null,
			// Exact fit
			widthFit: true,
			maxWidth: null,
			heightFit: true,
			maxHeight: null,
			marginWidth: 0,
			marginHeight: 0,
			minimumWidth: null,
			minimumHeight: null,
			follower: null,
			// Enough size
			horizontalDatum: $.scaler.CENTER,
		    verticalDatum: $.scaler.CENTER
		}, settings);
		
		switch (settings.action) {
			case $.scaler.EXACT_FIT:
				return methods.exactFit(settings, this);
			case $.scaler.ENOUGH_SIZE:
				return methods.enoughSize(settings, this);
			case $.scaler.CANCEL:
				return methods.cancel(this);
			case $.scaler.ADJUST:
				return methods.adjust(this);
			case $.scaler.RATIO:
				return methods.ratio(this);
		}
	};
	
	$.scaler = {
		DATA: 'famteam-scaler',
		
		EXACT_FIT: 'exactFit',
		ENOUGH_SIZE: 'enoughSize',
		CANCEL: 'cancel',
		ADJUST: 'adjust',
		RATIO: 'ratio',
		
	    CENTER: 0,
	    LEFT: 1,
	    RIGHT: 2,
	    TOP: 3,
	    BOTTOM: 4
	};
})(jQuery);